package com.gitee.wsl.prism4j.languages

import com.gitee.wsl.prism4j.GrammarUtils
import com.gitee.wsl.prism4j.GrammarUtils.require
import com.gitee.wsl.prism4j.Prism4j
import com.gitee.wsl.prism4j.Prism4j.Companion.grammar
import com.gitee.wsl.prism4j.Prism4j.Companion.pattern
import com.gitee.wsl.prism4j.Prism4j.Companion.token
import com.gitee.wsl.prism4j.annotations.Extend
import com.gitee.wsl.prism4j.Prism4j.Pattern

@Suppress("unused")
@Extend("clike")
object Prism_java {
    fun create(prism4j: Prism4j): Prism4j.Grammar {
        val keyword: Prism4j.Token? = token(
            "keyword",
            pattern(Pattern.compile("\\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\\b"))
        )

        val java = GrammarUtils.extend(
            require(prism4j, "clike"), "java",
            keyword!!,
            token(
                "number",
                pattern(
                    Pattern.compile(
                        "\\b0b[01]+\\b|\\b0x[\\da-f]*\\.?[\\da-fp-]+\\b|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e[+-]?\\d+)?[df]?",
                        Pattern.CASE_INSENSITIVE
                    )
                )
            ),
            token(
                "operator", pattern(
                    Pattern.compile(
                        "(^|[^.])(?:\\+[+=]?|-[-=]?|!=?|<<?=?|>>?>?=?|==?|&[&=]?|\\|[|=]?|\\*=?|\\/=?|%=?|\\^=?|[?:~])",
                        Pattern.MULTILINE
                    ),
                    true
                )
            )
        )

        GrammarUtils.insertBeforeToken(
            java, "function",
            token(
                "annotation", pattern(
                    Pattern.compile("(^|[^.])@\\w+"),
                    true,
                    false,
                    "punctuation"
                )
            )
        )

        GrammarUtils.insertBeforeToken(
            java, "class-name",
            token(
                "generics", pattern(
                    Pattern.compile(
                        "<\\s*\\w+(?:\\.\\w+)?(?:\\s*,\\s*\\w+(?:\\.\\w+)?)*>",
                        Pattern.CASE_INSENSITIVE
                    ),
                    false,
                    false,
                    "function",
                    grammar(
                        "inside",
                        keyword,
                        token("punctuation", pattern(Pattern.compile("[<>(),.:]")))
                    )
                )
            )
        )

        return java
    }
}
